﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Lesson1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            #region 输入输出
            /*
            // 输入输出
            // 按行输出
            Console.WriteLine("hello world");
            Console.WriteLine("hello world");
            // 不会换行
            Console.Write("hello world");
            Console.Write("hello world");

            Console.WriteLine();
            Console.WriteLine("用户请输入");

            // 检测用户输入的代码
            // 等待用户输入完毕后（按回车键）才会继续执行后面的代码
            // 用户可以输入很多信息，直到按回车结束
            Console.ReadLine();

            Console.WriteLine("用户输入完毕");

            // 检测用户是否按键了，只要按了键盘上的任意键 就会认为输入结束
            Console.ReadKey();

            Console.WriteLine("用户按了按键");
            */
            #endregion

            // 变量
            // 折叠代码 #region
            // 主要作用 让我们编程时 逻辑更清晰
            // 使用：输入#region后tab键自动补全，会出现以下代码，是成对出现的
            // 将中间包裹的代码折叠起来，避免代码太凌乱
            // 本质是：编辑器提供的预处理指令
            // 只会在编辑时有用，发布了代码或执行代码，它会被自动删除
            #region 如何声明变量
            // 变量：可以变化的容器
            // 变量声明 :    变量类型 变量名 = 初始值;
            int i = 1;
            // 变量类型 有14种
            // 变量名 自定义的
            // 初始值 一定要和变量类型统一

            // 变量类型：1、记住各种变量类型的关键字 2、记住各种不同变量类型的存储范围 3、记住各种不同变量类型的存储类型
            // 大类
            //  1、有符号的整形变量  能存储 一定范围 正负数包括0 的变量类型
            //      sbyte    -128 ~ 127
            //      int      -21亿多 ~ 21亿多
            //      short    -32768 ~ 32767
            //      long     -9百万兆多 ~ 9百万兆多
            //  2、无符号的整形变量 能存储一定范围 0和正数的变量类型
            //      byte        0~255
            //      uint        0~42亿多
            //      ushort      0~65536
            //      ulong       0~18百万兆多
            //  3、浮点数（小数）
            //      float       存储7/8位有效数字，根据编译器不同，有效数字也可能不一样
            float f = 0.123456789f;
            Console.WriteLine(f);          // 0.1234568
            float f1 = 0.0123456789f;
            Console.WriteLine(f1);          // 0.01234568       从非0数字开始计算的
            //      double      存储15~17位有效数字，抛弃的数字会四舍五入
            double d = 0.1234567899876543210;
            Console.WriteLine(d);          // 0.123456789987654     
            //      decimal     存储27~28位的有效数字，不建议使用, 也是会四舍五入
            decimal de = 0.1234567895465696651469189876504321m;
            Console.WriteLine(de);          // 0.1234567895465696651469189877   
                                            //  4、特殊类型
                                            //      bool        true/false         表示真假的数据类型，布尔类型
                                            //      char        'a'、'中'          用来存储单个字符的变量类型，字符类型
                                            //      string      "12abcAJ伏特加"    字符串类型，用来存储多个字符的，没有上限

            #endregion


            #region 为什么有那么多不同的变量类型
            // 不同的变量 存储的范围和类型不一样， 本质是占有的内存空间不同
            // 选择不同的数据（变量）类型装在不同的数据

            #endregion

            #region 多个相同的类型变量，同时声明
            int i1 = 1;
            float f2 = 3.2f;
            string str2 = "fbpc";

            int a1 = 1, a2 = 2, a3 = 3;

            #endregion

            #region 变量初始化
            int b1;
            //Console.WriteLine(b1);   // 直接用会报错
            b1 = 123;
            Console.WriteLine(b1);
            #endregion

            #region 变量的存储空间（内存中）
            // 通过sizeof方法，可以获取变量类型所占的内存空间（字节）
            int sbyteSize = sizeof(sbyte);
            Console.WriteLine("sbyte所占字节数是" + sbyteSize); // sbyte所占字节数是1
            int intSize = sizeof(int);
            Console.WriteLine("int所占字节数是" + intSize); // int所占字节数是4
            int shortSize = sizeof(short);
            Console.WriteLine("short所占字节数是" + shortSize); // short所占字节数是2
            int longSize = sizeof(long);
            Console.WriteLine("long所占字节数是" + longSize); // long所占字节数是8
            Console.WriteLine("************************************");
            int byteSize = sizeof(byte);
            Console.WriteLine("byte所占字节数是" + byteSize); // byte所占字节数是1
            int uintSize = sizeof(uint);
            Console.WriteLine("uint所占字节数是" + uintSize); // uint所占字节数是4
            int ushortSize = sizeof(ushort);
            Console.WriteLine("ushort所占字节数是" + ushortSize); // ushort所占字节数是2
            int ulongSize = sizeof(ulong);
            Console.WriteLine("ulong所占字节数是" + ulongSize); // ulong所占字节数是8
            Console.WriteLine("---------------------------------------");
            int floatSize = sizeof(float);
            Console.WriteLine("float所占字节数是" + floatSize); // float所占字节数是4
            int doubleSize = sizeof(double);
            Console.WriteLine("double所占字节数是" + doubleSize); // double所占字节数是8
            int decimalSize = sizeof(decimal);
            Console.WriteLine("decimal所占字节数是" + decimalSize); // decimal所占字节数是16
            Console.WriteLine("---------------------------------------");
            int boolSize = sizeof(bool);
            Console.WriteLine("bool所占字节数是" + boolSize); // bool所占字节数是1
            int charSize = sizeof(char);
            Console.WriteLine("char所占字节数是" + charSize); // char所占字节数是2
                                                        // sizeof无法得到 string 类型所占内存大小的，字符串长度是可变的
                                                        //int strSize = sizeof(string);
            #endregion

            #region 变量的本质
            // 变量的本质是2进制 -> 计算机中所有数据的本质都是二进制
            // 计算机中的存储单位最小是 bit （位），它只能表示0和1两个数字
            // 1bit就是1个数，0|1
            // 为表示方便，出现byte(字节)单位，由8个bit组成的存储单位
            // 1byte = 0000 0000

            #endregion


            #region 变量的命名规则
            // 1、不能重名
            // 2、不能以数字开头
            // 3、不能使用程序关键字命名
            // 4、不能有特殊符号（下划线除外）
            #endregion

            #region 变量命名规范
            // 英文、语义化
            // 驼峰命名 - 首字母小写，之后的单词首字母大写
            string myName = "";

            // 帕斯卡命名法 - 所有单词首字母都大写（函数、类）
            string MyName = "";

            // c#中大小写敏感
            #endregion

            #region 常量
            // 常量声明
            // 关键字 const
            // 固定写法： const 变量类型 常量名 = 初始值;

            // 常量特点
            // 1、必须初始化
            // 2、不能被修改
            // 作用： 声明一些不常用不变的变量
            const string Country = "chinese";

            const double PI = 3.141592653;
            #endregion

            #region 转义字符
            // 什么是转义字符
            // 它是字符串的一部分，用来表示一些特殊含义的字符

            // 固定写法  \字符
            // \和 不同的字符的组合 表示不同的含义

            // 常用转义字符
            // 单引号
            string str = "\'哈哈哈\'";
            Console.WriteLine(str);

            // 双引号
            str = "\"呵呵呵\"";
            Console.WriteLine(str);

            // 换行
            str = "12565565656\n5954894564";
            Console.WriteLine(str);

            // 斜杠
            str = "\\呼呼\\呼";
            Console.WriteLine(str);

            // 不常用转义字符
            // 制表符 \t    Tab键
            str = "hahaha\tmaker";
            Console.WriteLine(str);

            // 光标退格  运行起来才能看到用法
            str = "123\b123";   // 12123
            Console.WriteLine(str);

            // 空字符
            str = "123\0456";
            Console.WriteLine(str);

            // 警告音
            str = "\a";       // 运行后会有windows电脑出错时的声音
            Console.WriteLine(str);

            // 取消转移字符   @ 符 可以取消斜杠转移效果
            string strm = @"嘻嘻\嘻";   // 还有一种就是再加一个斜杠 "嘻嘻\\嘻"
            Console.WriteLine(strm);

            #endregion

            #region 类型转换 隐式转换

            // 相同大类型之间转换
            // 类型转换  就是不同变量类型之间的相互转换
            // 隐式转换的基本规则->不同类型之间自动转换
            // 大范围"装"小范围
            // 有符号的
            long l = 1;
            int ii = 1;
            short s = 1;
            sbyte b = 1;

            // 隐式转换 int隐式转换成了long   （java中的自动转换）
            // 可以用大范围类型装小范围的类型
            l = ii;
            l = s;
            l = b;
            ii = s;
            s = b;
            ii = b;

            // 无符号的
            ulong ul = 1;
            uint uii = 1;
            ushort us = 1;
            byte ub = 1;

            ul = uii;
            uii = us;
            us = ub;
            // ...

            // 浮点数
            decimal dem = 1.1m;
            double dd = 1.1;
            float ff = 1.1f;

            // decimal 这个类型没有办法用隐式转换的形式去存储 double和float的
            //dem = dd;  // 报错
            //dem = ff;  // 报错
            dd = ff;

            // 特殊类型
            // bool char  string 之间不存在隐式转换

            // 不同大类型之间的转换
            // 无符号不能装负数的，无符号的正数范围更大
            // 所以有符号不能隐式转换成无符号的

            // 有符号装无符号的
            //ii = uii;  // 报错 这个是无符号的数 可能会超过这个有符号数的范围
            ii = ub; // 这个 无符号的数不管是多少 都在有符号数的范围内，所以可以转

            // 浮点数可以装任何类型的整数
            ff = l;
            ff = ii;
            ff = s; 
            ff = b;
            ff = ul;
            // ...

            dem = l;
            dem = ii;
            dem = ul;
            // demcial可以装任何类型的整数

            // double  --->  float  ---->  所有整形（无符号、有符号）
            // decimal --->  所有整形（无符号、有符号）

            // 特殊类型和其它类型之间的转换
            // bool类型不能和其它类型相互隐式转换
            // char 不能隐式的存储其他类型
            // 但char可以隐式的转换成 int、uint、long、ulong、ushort、float、double、decimal 这几个整形或浮点型
            // string类型无法和其它类型进行隐式转换

            #endregion

            #region 类型转换 显式转换
            // 手动转换、强制转换
            // 括号强转
            // 作用：将高精度强制转换为低精度
            // 语法： 低精度变量类型 变量名 = (高精度变量类型)变量
            // 注意：强转后容易丢失精度(范围)

            // 有符号
            long l2 = 33000;
            int ii2;
            short s2;
            sbyte b2;

            s2 = (short)l2;
            Console.WriteLine(s2);  // 范围

            // 无符号
            byte by;
            uint uii2 = 100000;
            by = (byte)uii2;
            Console.WriteLine(by); 

            // 浮点型
            float ff2 = 1.1f;
            double dd2 = 1.2345678905;
            ff2 = (float)dd2;
            Console.WriteLine(ff2);  // 精度缩小

            // 无符号和有符号
            uint ui2 = 1;
            //int i2 = 1;
            int i2 = -1;
            ui2 = (uint)i2;
            Console.WriteLine(ui2); // 如果是负数，强转出来值范围精度会丢掉

            // 浮点和整形
            ii2 = (int)1.24f;
            Console.WriteLine(ii2);  // 浮点强转整形，会直接抛弃掉小数点后面的位数

            // char和数值类型
            ii2 = 'A';

            char c = (char)ii2;
            Console.WriteLine(c);  // A

            // bool和string不能通过括号强转

            // Parse法转换
            // 作用：把字符串类型转换成对应的类型
            // 语法：变量类型.Parse("字符串")
            // 注意：字符串必须能够转换成对应类型，否则报错, 还要考虑值的范围是否能被变量类型存储
            int i4 = int.Parse("123");
            Console.WriteLine(i4);

            ulong ul4 = ulong.Parse("123456789");
            Console.WriteLine(ul4);

            double d4 = double.Parse("123.45");
            Console.WriteLine(d4);

            bool b4 = bool.Parse("true");
            Console.WriteLine(b4);

            char c4 = char.Parse("b");
            Console.WriteLine(c4);


            // Covert法
            // 作用：准确的将各个类型之间相互转换
            // 语法：Covert.To目标类型(变量或常量)
            // 注意：填写的变量或常量必须正确 否则出错  填写的变量类型必须跟To后面的类型一致

            // 字符串转其他类型  如果把字符串转成对应类型，那字符串一定要合法合规，
            int i5 = Convert.ToInt32("123");
            Console.WriteLine(i5);
            i5 = Convert.ToInt32(1.6585f);
            Console.WriteLine(i5);   // 2   说明Convert精度更高，会四舍五入

            i5 = Convert.ToInt32(true);
            Console.WriteLine(i5);    // 1
            i5 = Convert.ToInt32(false);
            Console.WriteLine(i5);    // 0

            i5 = Convert.ToInt32('A');
            Console.WriteLine(i5);    // 65  ascii的值

            // 每一个类型都存在对应的Convert中的方法
            sbyte sb5 = Convert.ToSByte("123");
            Console.WriteLine(sb5);
            short s5 = Convert.ToInt16("123");  // short对应的就是2个字节，16位比特， 没有ToShort
            Console.WriteLine(s5);
            long l5 = Convert.ToInt64("123");
            Console.WriteLine(l5);

            byte b5 = Convert.ToByte("123");
            Console.WriteLine(b5);
            ushort us5 = Convert.ToUInt16("123");
            uint ui5 = Convert.ToUInt32("123");
            ulong ul5 = Convert.ToUInt64("123");

            float f5 = Convert.ToSingle("123.321");    // ToSingle就是单精度的意思
            double d5 = Convert.ToDouble("123.321");    // ToDouble就是双精度的意思
            decimal de5 = Convert.ToDecimal("123.321");    


            bool bool5 = Convert.ToBoolean("true");   // bool完整的就是boolean
            char char5 = Convert.ToChar("A");     




            // 其他类型转成string
            // 作用： 拼接打印
            // 语法： 变量.toString();
            string str6 = 1.ToString();
            Console.WriteLine(str6);
            str6 = true.ToString();
            str6 = 'A'.ToString();
            str6 = 1.2f.ToString();

            // 当进行字符拼接时，会自动调用 tostring 方法转成string
            Console.WriteLine("jwehw" + 1 + true);






            #endregion
        }
    }
}
